// SingleFuncDlg.cpp :Implementation file
//
//#include "stdafx.h"
//#include <afx.h>
//#include "LJV7_IF.h"
#include <vector>
#include <fstream>
#include <algorithm>

#include <iostream>
#include <iterator>
#include <Windows.h>
#include "SingleFuncDlg.h"
#include "OpenEthernetDlg.h"
#include "HighSpeedEthernetInitializeDlg.h"
#include "ThreadSafeBuffer.h"
#include "PreStartHighSpeedDlg.h"
#include "GetProfileDlg.h"
#include "DataExport.h"
#include <QtCore/QCoreApplication>
//#include "LJV7_IF.h"
//#pragma comment(lib,"LJV7_IF.lib")
volatile bool getprof=true;
LJV7IF_PROFILE_INFO CSingleFuncDlg::m_aProfileInfo[LJV7IF_DEVICE_COUNT];
CSingleFuncDlg::CSingleFuncDlg()
{
	 m_xvCurrentDeviceID=0;
	m_xvHeadNum=1;
	 m_xvXRange=0;
	m_xvBinning=0;
	m_xvIsEnvelope=TRUE;
	 m_xvXCompression=0;
	 m_xvSaveFilePath="D:/Projects/ly7300/data1.txt";
	 m_xvIsCountOnly=TRUE;
	 m_xvIsStartTimer=FALSE;
}
CSingleFuncDlg::~CSingleFuncDlg()
{
}

/*
 "Initialize" button clicked
*/
void CSingleFuncDlg::OnBnClickedBtnInitialize()
{

	int nRc = LJV7IF_Initialize();
	for (int i = 0; i < LJV7IF_DEVICE_COUNT; i++)
	{
		m_aDeviceData[i].m_deviceStatus = CDeviceData::DEVICESTATUS_NoConnection;
	}
}

/*
 "Ethernetopen" button clicked
*/
void CSingleFuncDlg::OnBnClickedBtnEthernetopen()
{
	// @Point
	// # Enter the "m_xvCurrentDeviceID" set here for the communication settings into the arguments of each DLL function.
	// # If you want to get data from multiple controllers, prepare and set multiple "m_xvCurrentDeviceID" values,
	//   enter these values into the arguments of the DLL functions, and then use the functions.	

	COpenEthernetDlg communicaionSettinDlg;
	//if(communicaionSettinDlg.DoModal() == IDOK)
	//{
		LJV7IF_ETHERNET_CONFIG ethernetConfig = communicaionSettinDlg.GetEthernetConfig();
		int nRc = LJV7IF_EthernetOpen(m_xvCurrentDeviceID, &ethernetConfig);

		CDeviceData::DEVICESTATUS status = (nRc == LJV7IF_RC_OK) ? CDeviceData::DEVICESTATUS_Ethernet : CDeviceData::DEVICESTATUS_NoConnection;
		m_aDeviceData[m_xvCurrentDeviceID].m_deviceStatus = status;
		m_aDeviceData[m_xvCurrentDeviceID].m_ethernetConfig = ethernetConfig;
	//}
}

/*
 "HighspeeddataEthernetCommunicationInitalize" button clicked
*/
void CSingleFuncDlg::OnBnClickedBtnHighspeeddataethernetcommunicationinitalize()
{
	//UpdateData(TRUE);

//	m_sendCommand = SENDCOMMAND_HIGHSPEEDDATAETHERNETCOMMUNICATIONINITALIZE;
	CHighSpeedEthernetInitializeDlg highSpeedEthernetInitializeDlg;
	highSpeedEthernetInitializeDlg.ethernetConfig = m_aDeviceData[m_xvCurrentDeviceID].m_ethernetConfig;
	//if(highSpeedEthernetInitializeDlg.DoModal() == IDOK)
	{
		// Clear the data
		//m_aDeviceData[m_xvCurrentDeviceID].m_vecMeasureData.clear();
		m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.clear();

		LJV7IF_ETHERNET_CONFIG config = highSpeedEthernetInitializeDlg.GetEthernetConfig();

		int nRc = LJV7IF_HighSpeedDataEthernetCommunicationInitalize(m_xvCurrentDeviceID, &config,
				(WORD)highSpeedEthernetInitializeDlg.m_xvHighSpeedPort, 
				(m_xvIsCountOnly ? CountProfileReceive : ReceiveHighSpeedData),
				highSpeedEthernetInitializeDlg.m_xvProfileCnt, m_xvCurrentDeviceID);
		// @Point
		// # When the frequency of calls is low, the callback function may not be called once per specified number of profiles.
		// # The callback function is called when both of the following conditions are met.
		//   * There is one packet of received data.
		//   * The specified number of profiles have been received by the time the call frequency has been met.
	
		
		if(nRc == LJV7IF_RC_OK)
		{
			m_aDeviceData[m_xvCurrentDeviceID].m_deviceStatus = CDeviceData::DEVICESTATUS_EthernetFast;
			m_aDeviceData[m_xvCurrentDeviceID].m_ethernetConfig = config;
		}
	}
}

/*
 "PreStartHighSpeedDataCommunication" button clicked
*/
void CSingleFuncDlg::OnBnClickedBtnPrestarthighspeeddatacommunication()
{
	//UpdateData(TRUE);
	//m_sendCommand = SENDCOMMAND_PRESTARTHIGHSPEEDDATACOMMUNICATION;

	CPreStartHighSpeedDlg preStartHighSpeedDlg;
	//if(preStartHighSpeedDlg.DoModal() == IDOK)
	{
		LJV7IF_HIGH_SPEED_PRE_START_REQ req = preStartHighSpeedDlg.getHighSpeedPreStartReq();
		// @Point
		// # SendPos is used to specify which profile to start sending data from during high-speed communication.
		// # When "Overwrite" is specified for the operation when memory full and 
		//   "0: From previous send complete position" is specified for the send start position,
		//    if the LJ-V continues to accumulate profiles, the LJ-V memory will become full,
		//    and the profile at the previous send complete position will be overwritten with a new profile.
		//    In this situation, because the profile at the previous send complete position is not saved, an error will occur.
		LJV7IF_PROFILE_INFO info;

		int nRc = LJV7IF_PreStartHighSpeedDataCommunication(m_xvCurrentDeviceID, &req, &info);
		//DisplayCommandLog(nRc, IDS_SCMD_PRESTARTHIGHSPEEDDATACOMMUNICATION);

		if(nRc == LJV7IF_RC_OK)
		{
			m_aProfileInfo[m_xvCurrentDeviceID] = info;
			//ShowProfileInfo(info);
		}
	}
}

/*
 "StartHighSpeedDataCommunication" button clicked
*/
void CSingleFuncDlg::OnBnClickedBtnStarthighspeeddatacommunication()
{
	//UpdateData(TRUE);

	CThreadSafeBuffer* threadSafeBuf = CThreadSafeBuffer::getInstance();
	threadSafeBuf->ClearBuffer(m_xvCurrentDeviceID);

	int nRc = LJV7IF_StartHighSpeedDataCommunication(m_xvCurrentDeviceID);
	// @Point
	//  If the LJ-V does not measure the profile for 30 seconds from the start of transmission,
	//  "0x00000008" is stored in dwNotify of the callback function.
	//DisplayCommandLog(nRc, IDS_SCMD_STARTHIGHSPEEDDATACOMMUNICATION);
	////while(getprof)
	//{
	//	CGetProfileDlg getProfileDlg;
	////	if(getProfileDlg.DoModal() == IDOK)
	//	LJV7IF_GET_PROFILE_REQ req = getProfileDlg.GetProfileReq();
	//	LJV7IF_GET_PROFILE_RSP rsp;
	//	LJV7IF_PROFILE_INFO profileInfo;
	//	DWORD dwOneDataSize = GetOneProfileDataSize();
	//	DWORD dwAllDataSize = dwOneDataSize * req.byGetProfCnt;
	//	vector<int> vecProfileData(dwAllDataSize/sizeof(DWORD));

	//	// Send Command
	//	int nRc = LJV7IF_GetProfile(m_xvCurrentDeviceID, &req, &rsp, &profileInfo, (DWORD*)&vecProfileData.at(0), dwAllDataSize);

	//	// Result output
	//	//	DisplayCommandLog(nRc, IDS_SCMD_GETPROFILE);

	//	if(nRc == LJV7IF_RC_OK)
	//	{
	//		// Clear the data
	//		//m_aDeviceData[m_xvCurrentDeviceID].m_vecMeasureData.clear();
	//		m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.clear();

	//		// Show response
	//		//ShowResponse(rsp);
	//		//ShowProfileInfo(profileInfo);


	//		// Analize the data
	//		int nDataUnitSize = (sizeof(LJV7IF_PROFILE_HEADER) + sizeof(int) * profileInfo.wProfDataCnt * profileInfo.byProfileCnt * (profileInfo.byEnvelope + 1) + sizeof(LJV7IF_PROFILE_FOOTER)) / sizeof(int);
	//		for(int i = 0; i < rsp.byGetProfCnt; i++)
	//		{
	//			int *pnBlock = &vecProfileData.at(nDataUnitSize * i);

	//			LJV7IF_PROFILE_HEADER* pHeader = (LJV7IF_PROFILE_HEADER*)pnBlock;
	//			int* pnProfileData			   = pnBlock + (sizeof(LJV7IF_PROFILE_HEADER) / sizeof(DWORD));
	//			LJV7IF_PROFILE_FOOTER* pFooter = (LJV7IF_PROFILE_FOOTER*)(pnProfileData + profileInfo.wProfDataCnt * profileInfo.byProfileCnt * (profileInfo.byEnvelope + 1));

	//			// Store the profile data
	//			m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.push_back(PROFILE_DATA(profileInfo, pHeader, pnProfileData, pFooter));
	//		}

	//	}
	//}
	////long num = m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.size()*800;
	//// Profile output(one profile only)
	//if(CDataExport::ExportProfile(&(m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.at(0)), m_xvSaveFilePath, 0))
	//{
	//	//ShowMessage(_T("###Save!!"));
	//	qDebug("Save!");
	//}
}


/*
 "GetProfile" button clicked
*/
void CSingleFuncDlg::OnBnClickedBtnGetprofile()
{
	int i=0;
	while(i<10)
	{
		CGetProfileDlg getProfileDlg;
	//	if(getProfileDlg.DoModal() == IDOK)
		{
			LJV7IF_GET_PROFILE_REQ req = getProfileDlg.GetProfileReq();
			LJV7IF_GET_PROFILE_RSP rsp;
			LJV7IF_PROFILE_INFO profileInfo;
			DWORD dwOneDataSize = GetOneProfileDataSize();
			DWORD dwAllDataSize = dwOneDataSize * req.byGetProfCnt;
			vector<int> vecProfileData(dwAllDataSize/sizeof(DWORD));

			// Send Command
			int nRc = LJV7IF_GetProfile(m_xvCurrentDeviceID, &req, &rsp, &profileInfo, (DWORD*)&vecProfileData.at(0), dwAllDataSize);
		
			// Result output
		//	DisplayCommandLog(nRc, IDS_SCMD_GETPROFILE);

			if(nRc == LJV7IF_RC_OK)
			{
				// Clear the data
				//m_aDeviceData[m_xvCurrentDeviceID].m_vecMeasureData.clear();
				//m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.clear();

				// Show response
				//ShowResponse(rsp);
				//ShowProfileInfo(profileInfo);
			

				// Analize the data
				int nDataUnitSize = (sizeof(LJV7IF_PROFILE_HEADER) + sizeof(int) * profileInfo.wProfDataCnt * profileInfo.byProfileCnt * (profileInfo.byEnvelope + 1) + sizeof(LJV7IF_PROFILE_FOOTER)) / sizeof(int);
				for(int i = 0; i < rsp.byGetProfCnt; i++)
				{
					int *pnBlock = &vecProfileData.at(nDataUnitSize * i);
				
					LJV7IF_PROFILE_HEADER* pHeader = (LJV7IF_PROFILE_HEADER*)pnBlock;
					int* pnProfileData			   = pnBlock + (sizeof(LJV7IF_PROFILE_HEADER) / sizeof(DWORD));
					LJV7IF_PROFILE_FOOTER* pFooter = (LJV7IF_PROFILE_FOOTER*)(pnProfileData + profileInfo.wProfDataCnt * profileInfo.byProfileCnt * (profileInfo.byEnvelope + 1));

					// Store the profile data
					m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.push_back(PROFILE_DATA(profileInfo, pHeader, pnProfileData, pFooter));
				}
				//long num=m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.size()*800;
				// Profile output(one profile only)
				//if(CDataExport::ExportProfile(&(m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.at(0)), m_xvSaveFilePath, 0))
				//{
				//	//ShowMessage(_T("###Save!!"));
				//	qDebug("Save!");
				//}
			}
		}
		i++;
	}
	//long num=m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.size();
	if(CDataExport::ExportProfile(&(m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.at(0)), m_xvSaveFilePath, 0))
	{
		//ShowMessage(_T("###Save!!"));
		qDebug("Save!");
	}
	m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.clear();
}

/*
 "StopHighSpeedDataCommunication" button clicked
*/
void CSingleFuncDlg::OnBnClickedBtnStophighspeeddatacommunication()
{
	getprof=false;
	int nRc = LJV7IF_StopHighSpeedDataCommunication(m_xvCurrentDeviceID);
	//DisplayCommandLog(nRc, IDS_SCMD_STOPHIGHSPEEDDATACOMMUNICATION);
}

/*
 "Save the profile" button clicked
*/
void CSingleFuncDlg::OnBnClickedSaveProfile()
{

	unsigned int profileNumber = 0;//m_xcSpinProfIndex.GetPos32();		// The limit is 2^16-1
	
	if(profileNumber >= m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.size())
	{
		//ShowMessage(_T("There is no profile specified.\r\n"));
		qDebug("There is no profile specified.\r\n");
		return;
	}

	//if(CDataExport::ExportProfile(&(m_aDeviceData[m_xvCurrentDeviceID].m_vecProfileData.at(0)), m_xvSaveFilePath, profileNumber))
	//{
	//	//ShowMessage(_T("Saved."));
	//	qDebug("Saved.\n");
	//}
}
/*
 callack function(count only)
 @param Pointer for profile data
 @param One profile data size
 @param Profile count
 @param notify
 @param UserID
*/
void CSingleFuncDlg::CountProfileReceive(BYTE* pBuffer, DWORD dwSize, DWORD dwCount, DWORD dwNotify, DWORD dwUser)
{
	// @Point
	// Take care to only implement storing profile data in a thread save buffer in the callback function.
	// As the thread used to call the callback function is the same as the thread used to receive data,
	// the processing time of the callback function affects the speed at which data is received,
	// and may stop communication from being performed properly in some environments.

	CThreadSafeBuffer* threadSafeBuf = CThreadSafeBuffer::getInstance();
	threadSafeBuf -> AddCount(dwUser, dwCount, dwNotify);
}

/*
 callack function(receive profile data)
 @param Pointer for profile data
 @param One profile data size
 @param Profile count
 @param notify
 @param UserID
*/
void CSingleFuncDlg::ReceiveHighSpeedData(BYTE* pBuffer, DWORD dwSize, DWORD dwCount, DWORD dwNotify, DWORD dwUser)
{
	// @Point
	// Take care to only implement storing profile data in a thread save buffer in the callback function.
	// As the thread used to call the callback function is the same as the thread used to receive data,
	// the processing time of the callback function affects the speed at which data is received,
	// and may stop communication from being performed properly in some environments.

	vector<PROFILE_DATA> vecProfileData;

	int nProfDataCnt = (dwSize - sizeof(LJV7IF_PROFILE_HEADER) - sizeof(LJV7IF_PROFILE_FOOTER)) / sizeof(DWORD);
	
	for(DWORD i = 0; i < dwCount; i++)
	{
		BYTE *pbyBlock = pBuffer + dwSize * i;
	
		LJV7IF_PROFILE_HEADER* pHeader    = (LJV7IF_PROFILE_HEADER*)pbyBlock;
		int* pnProfileData                = (int*)(pbyBlock + sizeof(LJV7IF_PROFILE_HEADER));
		LJV7IF_PROFILE_FOOTER* pFooter    = (LJV7IF_PROFILE_FOOTER*)(pbyBlock + dwSize - sizeof(LJV7IF_PROFILE_FOOTER));
	
		vecProfileData.push_back(PROFILE_DATA(m_aProfileInfo[dwUser], pHeader, pnProfileData, pFooter));
	}
	CThreadSafeBuffer* threadSafeBuf = CThreadSafeBuffer::getInstance();
	threadSafeBuf->Add(dwUser, vecProfileData, dwNotify);	
}
/*
 Get one profile size for current specified state
 @return one profile data size(byte)
*/
int CSingleFuncDlg::GetOneProfileDataSize()
{
	// Get the Profile Count
	int nProfileCnt = 800;
	//int nProfileCnt = 0;
	//CString strXRange;
	//m_xcXRange.GetLBText(m_xvXRange, strXRange);
	//if(strXRange == _T("FULL"))
	//{
	//	nProfileCnt = 800;
	//}
	//else if(strXRange == _T("MIDDLE"))
	//{
	//	nProfileCnt = 600;
	//}
	//else if(strXRange == _T("SMALL"))
	//{
	//	nProfileCnt = 200;
	//}

	//// Get the compressibility
	int nCompression = 1;
	//int nCompression = 0;
	//CString strCompresion;
	//m_xcXCompression.GetLBText(m_xvXCompression, strCompresion);
	//if(strCompresion == _T("OFF"))
	//{
	//	nCompression = 1;
	//}
	//else if(strCompresion == _T("2"))
	//{
	//	nCompression = 2;
	//}
	//else if(strCompresion == _T("4"))
	//{
	//	nCompression = 4;
	//}

	UINT retBuffSize = 0;											// Buffer size (in units of bytes)
	int basicSize = nProfileCnt / (m_xvBinning + 1);				// Basic size
	basicSize /= nCompression;

	retBuffSize += (UINT)basicSize * 2U;	// Number of headers
	retBuffSize *=  2U ;	                    // Envelope setting
	//retBuffSize += (UINT)basicSize * (m_xvHeadNum == 0 ? 1U : 2U);	// Number of headers
	//retBuffSize *= (m_xvIsEnvelope ? 2U : 1U);						// Envelope setting
	retBuffSize *= sizeof(UINT);									//in units of bytes

	retBuffSize += sizeof(LJV7IF_PROFILE_HEADER);					// Sizes of the header and footer structures
	retBuffSize += sizeof(LJV7IF_PROFILE_FOOTER);

	return retBuffSize;
}

